package com.opennews.openplatform.security;

import com.opennews.openplatform.myspringbootcore.dto.ActiveToken;
import com.opennews.openplatform.myspringbootcore.security.ActiveTokenManager;
import com.opennews.openplatform.myspringbootcore.util.DateHelper;
import lombok.RequiredArgsConstructor;
import org.jooq.DSLContext;
import org.springframework.stereotype.Component;

import java.util.List;

import static com.opennews.openplatform.entity.Tables.USER_ACTIVE_TOKEN;

@RequiredArgsConstructor
@Component
public class SecurityActiveTokenManager implements ActiveTokenManager {
    // It only caches access tokens since refresh tokens never expire.
    // By using cached access tokens would reduce access to database.
    private static List<ActiveToken> cachedUserActiveTokens;

    private final DSLContext dslContext;

    @Override
    public boolean isActiveAccessToken(String username, String deviceId, String accessToken) {
        // Checks from Redis
        //        String cachedUsername = redisTemplate.opsForValue().get(accessToken);
        //
        //        return cachedUsername != null && cachedUsername.equals(username);

        return getCachedUserActiveTokens().stream().anyMatch(p -> p.getUsername().equals(username) &&
                p.getDeviceId().equals(deviceId) &&
                p.getAccessToken().equals(accessToken));
    }

    @Override
    public List<ActiveToken> getCachedUserActiveTokens() {
        if (cachedUserActiveTokens == null) {
            reloadCachedUserActiveTokenRecords();
        }

        return cachedUserActiveTokens;
    }

    @Override
    public void reloadCachedUserActiveTokenRecords() {
        cachedUserActiveTokens = dslContext
                .selectFrom(USER_ACTIVE_TOKEN)
                .where(
                        USER_ACTIVE_TOKEN.DATE_EXPIRED.ge(DateHelper.getCurrentLocalDateTime())
                                .and(USER_ACTIVE_TOKEN.ENABLED.isTrue())
                )
                .fetch().map((record) -> ActiveToken.builder()
                        .username(record.getUsername())
                        .deviceId(record.getDeviceId())
                        .accessToken(record.getAccessToken())
                        .build()
                );
    }
}
